package com.cn.lp.openapi.base;

import com.cn.lp.common.utils.BlankAide;
import com.cn.lp.openapi.aop.FeignClientAOP;
import com.cn.lp.openapi.processor.GetRequestParamParameterProcessor;
import com.cn.lp.openapi.processor.RequestHeaderParamParameterProcessor;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import feign.Util;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
import org.springframework.cloud.openfeign.annotation.RequestHeaderParameterProcessor;
import org.springframework.cloud.openfeign.annotation.RequestParamParameterProcessor;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;

import java.util.Collection;
import java.util.Map;

@Configuration
@ComponentScan(basePackages = "org.springframework.cloud.openfeign.annotation",
includeFilters = {
    @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {AnnotatedParameterProcessor.class})
},
excludeFilters = {
    @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {RequestHeaderParameterProcessor.class, RequestParamParameterProcessor.class})
})
public class OpenApiClientConfiguration implements EnvironmentAware {

    private Environment environment;

    @Bean
    public WebMvcRegistrations feignWebRegistrations() {
        return new FeignMvcRegistrations();
    }

    @Bean
    @ConditionalOnMissingBean
    public RequestHeaderParamParameterProcessor getRequestHeaderParamParameterProcessor() {
        return RequestHeaderParamParameterProcessor.build(true, Util.UTF_8);
    }

    @Bean
    @ConditionalOnMissingBean
    public GetRequestParamParameterProcessor getGetRequestParamParameterProcessor() {
        return GetRequestParamParameterProcessor.build(false, Util.UTF_8);
    }

    @Bean
    @ConditionalOnClass(LoadBalancerFeignClient.class)
    @ConditionalOnProperty(value = "openApi.dynClient.enabled")
    public FeignClientAOP feignClientAOP() {
        return new FeignClientAOP();
    }

    @Bean
    public RequestInterceptor getRequestInterceptor() {
        return new RequestInterceptor() {
            @Override
            public void apply(RequestTemplate template) {
                Map<String, Collection<String>> headers = template.headers();
                if(BlankAide.isNotBlank(headers)) {
                    String dynUrl = "";
                    Collection<String> dynUrlKeys = headers.get(OpenApiClientConstants.DYN_URL);
                    if(BlankAide.isNotBlank(dynUrlKeys)) {
                        String dynUrlKey = dynUrlKeys.stream().findFirst().get();
                        dynUrl = environment.getProperty(dynUrlKey);
                    }
                    String dynName = "";
                    Collection<String> dynNameKeys = headers.get(OpenApiClientConstants.DYN_NAME);
                    if(BlankAide.isNotBlank(dynNameKeys)) {
                        String dynNameKey = dynNameKeys.stream().findFirst().get();
                        dynName = environment.getProperty(dynNameKey);
                    }
                    if(BlankAide.isNotBlank(dynUrl) || BlankAide.isNotBlank(dynName)) {
                        String url = "";
                        if (!StringUtils.hasText(dynUrl)) {
                            if (!dynName.startsWith("http")) {
                                url = "http://" + dynName;
                            }
                            else {
                                url = dynName;
                            }
                        } else if(!dynUrl.startsWith("http")) {
                            url = "http://" + dynUrl;
                        } else {
                            url = dynUrl;
                        }
                        String path = template.path();
                        if (StringUtils.hasLength(path)) {
                            if (!path.startsWith("/")) {
                                path = "/" + path;
                            }
                            if (path.endsWith("/")) {
                                path = path.substring(0, path.length() - 1);
                            }
                        }
                        url = url + path;
                        template.uri("");
                        template.target(url);
                    }
                }
            }
        };
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
}
